package project5;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.StringTokenizer;

public class RABID
{
	private static Index rabidIndex;

	public static void main(String args[])
	{
		if (0 != args.length)
		{
			System.out.println("RABID should be invoked without arguments.");
			System.exit(0);
		}

		ArrayList<String> querywords;
		ArrayList<FreqRepresenter> cardinalityArray2;
		ArrayList<FreqRepresenter> similarityArray;
		ArrayList<FreqRepresenter> similarityArray2;

		try
		{
			String position = "DTI.out";
			System.out.println("Welcome to the RABID");

			String command;

			FileInputStream in = new FileInputStream(position); 
			ObjectInputStream sIn = new ObjectInputStream(in);
			rabidIndex = (Index) sIn.readObject();

			System.out.println("The index was created at " + new Date(rabidIndex.dateTimeofCreation));
			BufferedReader in6 = new BufferedReader(new InputStreamReader(System.in));

			do
			{
				querywords = new ArrayList<String>();
				cardinalityArray2 = new ArrayList<FreqRepresenter>();
				similarityArray = new ArrayList<FreqRepresenter>();
				similarityArray2 = new ArrayList<FreqRepresenter>();
				
				System.out.print("???  ");
				command = in6.readLine();
				StringTokenizer st = new StringTokenizer(command);

				if (command.equals("STATS"))
				{
					System.out.println("===STATS of the Corpus are====");
					System.out.println("# of files in the corpus " +rabidIndex.noOfFilesInCorpus);
					System.out.println("# of words   "+rabidIndex.noOfWordsInCorpus);
					System.out.println("# of characters "+rabidIndex.noOfCharacters);
					continue;
				}
				else if (command.equals("INDEX"))
				{
					System.out.println("===INDEX Information====");
					System.out.println("Name of the index file "+rabidIndex.indexFileName);
					System.out.println("Creation Date and Time " + new Date(rabidIndex.dateTimeofCreation));
					System.out.println("Directory of index file "+rabidIndex.directoryOfIndexFile);
					System.out.println("Size of the index file "+rabidIndex.indexSizeInBytes);
					continue;
				}
				else if (command.startsWith("SIMILAR TO"))
				{
					System.out.println("helloz i came here");
					String fileName = (String)querywords.get(2);

					querywords.remove("SIMILAR");
					querywords.remove("TO");

					DocumentIndexer di = new DocumentIndexer(rabidIndex.indexWords);
					ArrayList<String> wordsArray = new ArrayList<String>();

					//create word out of the file
					WordCounter wc = new WordCounter();
					try
					{
						wordsArray = wc.WordCreator(fileName);
					}
					catch(ProjectException pe)
					{
						//TODO fill out.
					}

					FreqRepresenter similarTo = di.bitVectorCreator(fileName, wordsArray);

					//this is the query bit vector
					BitSet tempSmfr = similarTo.doesContain;

					similarityArray = rabidIndex.freqIndexer;

					for (FreqRepresenter frFromArray : similarityArray)
					{
						BitSet tempFromArray = frFromArray.doesContain;
						tempFromArray.and(tempSmfr);
						frFromArray.cardinalityAfterAnding = tempFromArray.cardinality();

						similarityArray2.add(frFromArray);
					}

					Comparator<FreqRepresenter> comparator = Collections.reverseOrder();
					Collections.sort(similarityArray2, comparator);

					int innerCounter = 0;
					for (FreqRepresenter displayer : similarityArray2)
					{
						if (innerCounter >= 7)
						{
							break;
						}
						if(displayer.cardinalityAfterAnding>0)
						{
							System.out.println("Printing from RABID line 134");
							System.out.println(displayer.cardinalityAfterAnding
									+ " " + displayer.fileName);
						}
						innerCounter++;
					}
				}
				else if (command.startsWith("DISPLAY"))
				{
					while (st.hasMoreTokens())
					{
						querywords.add(st.nextToken());
					}
					
					querywords.remove("DISPLAY");
					
					if (1 != querywords.size())
					{
						ErrorUtility.handleError(new ProjectException(ErrorUtility.ILL_RABID_COMMAND));
						continue;
					}
					
					String fName = querywords.get(0);
					File testFile = new File(fName);
					try
					{
						System.out.println("Original file contents: " + getContents(testFile));
					}
					catch (ProjectException pe)
					{
						ErrorUtility.handleError(pe);
					}
				}
				else if (command.startsWith("QUERY"))
				{
					while(st.hasMoreTokens())
					{
						querywords.add(st.nextToken());
					}
					
					// Pull the command out of the words list.
					querywords.remove("QUERY");

					DocumentIndexer di = new DocumentIndexer(rabidIndex.indexWords);
					FreqRepresenter queryfr = di.bitVectorCreator("QueryFile", querywords);

					//this is the query bit vector
					BitSet tempQuerfr = queryfr.doesContain;
					for (FreqRepresenter frFromArray : rabidIndex.freqIndexer)
					{
						BitSet tempFromArray = (BitSet)(frFromArray.doesContain).clone();
						tempFromArray.and(tempQuerfr);
						
						frFromArray.cardinalityAfterAnding = tempFromArray.cardinality();

						cardinalityArray2.add(frFromArray);
					}

					Collections.sort(cardinalityArray2, Collections.reverseOrder());

					Iterator<FreqRepresenter> ret = cardinalityArray2.iterator();
					int innerCounter = 0;

					while(ret.hasNext() && (innerCounter < 7))
					{
						FreqRepresenter displayer = (FreqRepresenter) ret.next();

						if (displayer.cardinalityAfterAnding > 0)
						{
							System.out.println(displayer.cardinalityAfterAnding
									+ " " + displayer.fileName);
							innerCounter++;
						}
					}
				}
				else if (command.equals("QUIT"))
				{
					System.out.println("Terminated");
					System.exit(0);
				}
				else
				{
					System.out.println("Invalid command.");
				}
			}
			while(!command.equals("QUIT"));

		}
		catch (Exception e)
		{
			e.printStackTrace();
			ErrorUtility.handleError (
					new ProjectException(ErrorUtility.UNCAUGHT_EXCEPTION));
		}
	}

	public static String getContents(File aFile) throws ProjectException
	{
		System.out.println(aFile.getAbsolutePath());
		
		if (!aFile.exists())
		{
			throw new ProjectException(ErrorUtility.CANNOT_FIND_FILE);
		}
		
		StringBuilder contents = new StringBuilder();
		BufferedInputStream bin = null;
		int read;
		
		try
		{
			 bin = new BufferedInputStream(new FileInputStream(aFile));
			 while((read = bin.read()) != -1)
			 {
				 contents.append((char) read);
			 }
		}
		catch (IOException ioe)
		{
			throw new ProjectException(ErrorUtility.CANNOT_READ_FILE);
		}
		finally
		{
			if (null != bin)
			{
				try
				{
					bin.close();
				}
				catch (IOException ioe)
				{
					//Ignore
				}
			}
		}

		return contents.toString();
	}
}